﻿using EventHandlerDemo.Domain.Bases;
using EventHandlerDemo.Domain.OrderEventLogs;
using EventHandlerDemo.Domain.Orders;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace EventHandlerDemo.Infrastructure.EFCore
{
    public class AppDbContext : DbContext
    {
        private readonly IPublisher _publisher;

        public AppDbContext(DbContextOptions<AppDbContext> options, IPublisher publisher) : base(options)
        {
            _publisher = publisher;
        }

        public DbSet<Order> Orders { get; set; }
        public DbSet<OrderEventLog> OrderEventLogs { get; set; }

        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
        {
            var entityChangeReport = new EntityChangeReport();

            foreach (var entry in ChangeTracker.Entries().ToList())
            {
                var generatesDomainEventsEntity = entry.Entity as IGeneratesDomainEvents;
                if (generatesDomainEventsEntity == null)
                {
                    continue;
                }

                if (generatesDomainEventsEntity.DomainEvents == null || generatesDomainEventsEntity.DomainEvents.Count <= 0)
                {
                    continue;
                }

                entityChangeReport.DomainEvents.AddRange(generatesDomainEventsEntity.DomainEvents.Select(eventData => new DomainEventEntry(entry, eventData)));
                generatesDomainEventsEntity.DomainEvents.Clear();
            }

            var result = await base.SaveChangesAsync(cancellationToken);

            foreach (var domainEvent in entityChangeReport.DomainEvents)
            {
                await _publisher.Publish(domainEvent.EventData, cancellationToken);
            }

            return result;
        }
    }
}
